home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Tool Chest / Testing & Debugging / Virtual User / Virtual User Current Release / Examples / External Tool Templates / CPlus Tool Template / AERequest.cp < prev    next >
Encoding:
Text File  |  1998-06-04  |  32.3 KB  |  1,281 lines  |  [TEXT/MPS ]

  1. /*
  2.  *    File:        AERequest.cp
  3.  *
  4.  *    Contains:    xxx put contents here xxx
  5.  *
  6.  *    Written by:    Rick Violet
  7.  *
  8.  *    Copyright:    © 1992 by Apple Computer, Inc., all rights reserved.
  9.  *
  10.  *    Change History (most recent first):
  11.  *
  12.  *        <1+>     5/18/93    RV        Now accepts parameters of type 'true', 'false', and 'BOOL' from
  13.  *                                    the Apple Events
  14.  *        <7+>    11/19/92    RV        
  15.  *                11/18/92    RV        xxx put comment here xxx
  16.  *
  17.  *    To Do:
  18.  */
  19.  
  20. #ifndef        __APPLICATION__
  21. #include        "Application.h"
  22. #endif
  23.  
  24. #ifndef        __AERequest__
  25. #include        "AERequest.h"
  26. #endif
  27.  
  28. #ifndef        __RequestDispatcher__
  29. #include        "RequestDispatcher.h"
  30. #endif
  31.  
  32. #ifndef        __ERRORS__
  33. #include        <Errors.h>
  34. #endif
  35.  
  36. #ifndef        __PACKAGES__
  37. #include        <Packages.h>
  38. #endif
  39.  
  40. //—————————————————————————————————————————————————————————————————————————————————————
  41. //                                Global Variables
  42. //—————————————————————————————————————————————————————————————————————————————————————
  43. extern    RequestDispatcher*        gTheRequestDispatcher;
  44. extern    Application*            gTheApplication;
  45.  
  46. //—————————————————————————————————————————————————————————————————————————————————————
  47. //    AERequestHandler - handles 'v.u.' 'extc' apple event
  48. //—————————————————————————————————————————————————————————————————————————————————————
  49. pascal    OSErr  
  50. AERequestHandler( AppleEvent* pMessage, AppleEvent* pReply, long )
  51. {
  52.     OSErr            tErr = noErr;
  53.     AERequest*        tReq;
  54.     AEKeyword        tVUEventClass = kVUAETool;
  55.     AEDesc            tDesc;
  56.     Boolean            tUseStandardReplyType;
  57.  
  58.     
  59.         //————    APPLESCRIPT COMPATIBILITY CHECK:
  60.         //————    Use the AppleScript protocol unless we must use the VU 2.0.x protocol.
  61.         //————    A target parameter (noErr) means Virtual User sent the request.
  62.         //————    An error (-1701) means AppleScript or other non-VU entity.
  63.     tUseStandardReplyType = true;
  64.     tErr =  AEGetParamDesc( pMessage, kVUAESrvcTarget, typeWildCard, &tDesc );
  65.  
  66.     if( tErr == noErr )
  67.     {
  68.             //————    Free the memory occupied by the target parameter AEDesc.
  69.         AEDisposeDesc( &tDesc );
  70.         
  71.             //————    No protocol version parameter (-1701) means VU 2.0 or 2.0.1.
  72.         tErr =  AEGetParamDesc( pMessage, kVUAEProtocolVersion, typeWildCard, &tDesc );
  73.         if( tErr == errAEDescNotFound )
  74.         {
  75.             tUseStandardReplyType = false;
  76.         }
  77.         else
  78.         {
  79.                 //————    Free the memory occupied by the version parameter AEDesc.
  80.             AEDisposeDesc( &tDesc );
  81.         }
  82.     }
  83.     else
  84.     {
  85.             //————    reset tErr because this error was informative, not fatal
  86.         tErr = noErr;
  87.     }
  88.  
  89.     if( !tUseStandardReplyType )
  90.     {
  91.             //————    Change reply class id to 'v.u.' for VU 2.0.x compatibility
  92.             //————    Do this as early as possible before errors can occur
  93.         tErr =  AEPutAttributePtr(    pReply,
  94.                                     keyEventClassAttr,
  95.                                     typeType,
  96.                                     (Ptr) &tVUEventClass,
  97.                                     sizeof( OSType ) );
  98.     
  99.         if( tErr != noErr )
  100.         {
  101.                 //————    error encountered, return err code to AE Manager
  102.             return tErr;
  103.         }
  104.     }
  105.  
  106.         //————    Construct AERequest and put it in the request queue
  107.     tReq = new AERequest( pMessage, pReply, tUseStandardReplyType );
  108.     if( tReq != nil )
  109.     {
  110.         if( tReq->IsACancelRequest() )
  111.         {
  112.                 //————    VU does not need a reply from a Cancel request
  113.                 //————    so we can delete it before it is suspended.
  114.             gTheRequestDispatcher->DoCancelReq( tReq );
  115.             delete tReq;
  116.             return noErr;
  117.         }
  118.         
  119.         tErr = tReq->Initialize();
  120.         if( tErr != noErr )
  121.         {
  122.             delete tReq;
  123.         }
  124.         else
  125.         {
  126.             gTheRequestDispatcher->QueueRequest( tReq );
  127.         }
  128.     }
  129.     else
  130.     {
  131.             //————    assume a memFullErr if new AERequest failed
  132.         tErr = -108;
  133.     }
  134.  
  135.     return( tErr );
  136. }
  137.  
  138. //—————————————————————————————————————————————————————————————————————————————————————
  139. //    AERequest::AERequest    -    constructor.
  140. //—————————————————————————————————————————————————————————————————————————————————————
  141. AERequest::AERequest( AppleEvent* pMessage, AppleEvent* pReply, Boolean pUseStandardReplyType )
  142. {
  143.     fMessagePtr             = pMessage;
  144.     fReplyPtr               = pReply;    
  145.     fSuspended                 = false;
  146.     fReturnID                 = 0;
  147.     fHaveResetTimerMsg        = false;
  148.     fSendResetTicks            = TickCount();            //————    Set to current Ticks
  149.     fUseStandardReplyType    = pUseStandardReplyType;
  150. }
  151.  
  152. //—————————————————————————————————————————————————————————————————————————————————————
  153. //    AERequest::~AERequest    -    destructor.
  154. //—————————————————————————————————————————————————————————————————————————————————————
  155. AERequest::~AERequest()
  156. {
  157.  
  158.         //————    Only if we successfully suspended the AppleEvent 
  159.         //————    and we did NOT successfully resume it are we 
  160.         //————    responsible for disposing of the AppleEvent descriptors;
  161.         //————    Otherwise, the AppleEvent Manager automatically disposes of them 
  162.         //————    when we return from the Handler (or resume after suspending).
  163.     if( fSuspended )
  164.     {
  165.         AEDisposeDesc( fMessagePtr );
  166.         AEDisposeDesc( fReplyPtr );
  167.     }
  168.     
  169.         //————    if we created a TimeOut Reset AppleEvent, then dispose of it
  170.     if( fHaveResetTimerMsg )
  171.     {
  172.         AEDisposeDesc( &fResetTimerMsg );
  173.     }
  174. }
  175.  
  176. //—————————————————————————————————————————————————————————————————————————————————————
  177. //    AERequest::GetIdentifierOfRequesttoCancel    -    return the request
  178. //        identifier of the request to cancel. 
  179. //        This method is for use with cancel requests only.
  180. //—————————————————————————————————————————————————————————————————————————————————————
  181. long
  182. AERequest::GetIdentifierOfRequesttoCancel()
  183. {
  184.     ScriptValue*    tVal;
  185.     ValueKind        tVKind = kVUAnyKind;
  186.     long            tResult = 0;
  187.     
  188.     GetNthParam( 1, tVal, tVKind );
  189.     if( tVal )
  190.     {
  191.         switch( tVKind )
  192.         {
  193.             case kVULongNumberKind:
  194.             {
  195.                 tResult = ((VULongNumber*)tVal)->GetNumber();
  196.             }
  197.             break;
  198.             
  199.             case kVUStringKind:
  200.             {
  201.                 stringtonum( ((VUString*)tVal)->GetText(), &tResult );
  202.             }
  203.             break;
  204.         }
  205.     }
  206.     
  207.     return tResult;
  208. }
  209.  
  210. //—————————————————————————————————————————————————————————————————————————————————————
  211. //    AERequest::InstallAppleEventHandler    - Install an AppleEvent Handler
  212. //                                                into the AE dispatch table for receiving 
  213. //                                                Apple Events from V.U.
  214. //—————————————————————————————————————————————————————————————————————————————————————
  215. OSErr
  216. AERequest::InstallAppleEventHandler()
  217. {    
  218.     return AEInstallEventHandler(    kVUAETool,
  219.                                       kVUAESendService,
  220.                                     NewAEEventHandlerProc(AERequestHandler),
  221.                                        0, false );
  222.  
  223. }
  224.  
  225. //—————————————————————————————————————————————————————————————————————————————————————
  226. //    AERequest::SetErrorCode    - set the Error code for this request
  227. //—————————————————————————————————————————————————————————————————————————————————————
  228. void
  229. AERequest::SetErrorCode( OSErr tErr )
  230. {
  231.     if( fReplyPtr != nil )
  232.     {
  233.         AEPutAttributePtr(    fReplyPtr,
  234.                             keyErrorNumber,
  235.                             typeShortInteger,
  236.                             (Ptr)&tErr,
  237.                             sizeof( OSErr ) );
  238.     }
  239.     
  240.     Request::SetErrorCode( tErr );
  241. }
  242.  
  243. //—————————————————————————————————————————————————————————————————————————————————————
  244. //    AERequest::SetErrorMessage    - set the Error message for this request
  245. //—————————————————————————————————————————————————————————————————————————————————————
  246. void
  247. AERequest::SetErrorMessage( char* tErrText )
  248. {
  249.     if( fReplyPtr != nil )
  250.     {
  251.         AEPutAttributePtr(    fReplyPtr,
  252.                             keyErrorString,
  253.                             typeChar,
  254.                             (Ptr)tErrText,
  255.                             strlen( tErrText ) );
  256.     }
  257.     
  258.     Request::SetErrorMessage( tErrText );
  259. }
  260.  
  261. //—————————————————————————————————————————————————————————————————————————————————————
  262. //    AERequest::Initialize    -    initialize the Request
  263. //                                        Transfers info in AppleEvents to the
  264. //                                        Request object
  265. //—————————————————————————————————————————————————————————————————————————————————————
  266. OSErr
  267. AERequest::Initialize()
  268. {
  269.     OSErr    tErr = noErr;
  270.  
  271.         //————    Suspend processing of the AppleEvent by the AE Manager.
  272.         //————    This prevents the reply AppleEvent from being sent back and deleted
  273.         //————    when this routine returns ( actually it's when the AE Handler returns ).
  274.     tErr = AESuspendTheCurrentEvent( fMessagePtr );
  275.     if( tErr != noErr )
  276.     {
  277.         fSuspended     = false;
  278.         return tErr;
  279.     }
  280.     else
  281.     {
  282.         fSuspended     = true;
  283.     }
  284.     
  285.         //————    see AERequest.cp and Request.cp for details
  286.     FixAEManagerBugPart1();
  287.     
  288.     
  289.         //————    Get the return ID of the AppleEvent
  290.     tErr = SetupReturnID();
  291.     if( tErr != noErr )
  292.     {
  293.         SetErrorCode( tErr );
  294.         SetErrorMessage( "Failed to extract return id from AppleEvent." );
  295.         return tErr;
  296.     }
  297.  
  298.         //————    Get the Service Indentifier from the AppleEvent
  299.         //————    This string identifies which service is requested
  300.     tErr = SetupSeviceIdentifier();
  301.     if( tErr != noErr )
  302.     {
  303.         SetErrorCode( tErr );
  304.         SetErrorMessage( "Failed to extract service identifier." );
  305.         return tErr;
  306.     }
  307.  
  308.         //————    Get the service parameters from the AppleEvent
  309.         //————    and install them into this Request.
  310.     tErr = SetupParameterList();
  311.     if( tErr != noErr )
  312.     {
  313.         SetErrorCode( tErr );
  314.         SetErrorMessage( "Failed to extract parameters." );
  315.         return tErr;
  316.     }
  317.  
  318.         //————    Get the service parameters from the AppleEvent
  319.         //————    and install them into this Request.
  320.     tErr = SetupRequestIdentifier();
  321.     if( tErr != noErr )
  322.     {
  323.         SetErrorCode( tErr );
  324.         SetErrorMessage( "Failed to extract return ID." );
  325.         return tErr;
  326.     }
  327.     
  328.         //————    Call Parent class's Initialize
  329.     tErr = Request::Initialize();
  330.     if( tErr != noErr )
  331.     {
  332.         return tErr;
  333.     }
  334.     
  335.     return noErr;
  336. }
  337.  
  338. //—————————————————————————————————————————————————————————————————————————————————————
  339. //    AERequest::SetupReturnID    -    Get the AppleEvent's return ID
  340. //—————————————————————————————————————————————————————————————————————————————————————
  341. OSErr
  342. AERequest::SetupReturnID()
  343. {
  344.     OSErr        tErr;
  345.     long        tResult;
  346.     DescType    tActualType;
  347.     Size        tActualSize;
  348.     
  349.     tErr = AEGetAttributePtr(    fMessagePtr,
  350.                                 keyReturnIDAttr,
  351.                                 typeLongInteger,
  352.                                 &tActualType,
  353.                                 (Ptr)&tResult,
  354.                                 sizeof( tResult ),
  355.                                 &tActualSize );
  356.     if( tErr == noErr )
  357.     {
  358.         fReturnID = tResult;
  359.     }
  360.     else
  361.     {
  362.         fReturnID = 0;
  363.     }
  364.     return tErr;
  365. }
  366.  
  367. //—————————————————————————————————————————————————————————————————————————————————————
  368. //    AERequest::SetupSeviceIdentifier    -    Get the AppleEvent's direct parameter
  369. //                                It contains the text which identifies
  370. //                                which service is requested
  371. //—————————————————————————————————————————————————————————————————————————————————————
  372. OSErr
  373. AERequest::SetupSeviceIdentifier()
  374. {
  375.     OSErr        tErr;
  376.     char        tText[256];
  377.     DescType    tActualType;
  378.     Size        tActualSize;
  379.     
  380.     tErr = AEGetParamPtr(    fMessagePtr,
  381.                             kVUAESrvcName,
  382.                             typeChar,
  383.                             &tActualType,
  384.                             (Ptr)tText,
  385.                             255,
  386.                             &tActualSize );
  387.     if( tErr == noErr )
  388.     {
  389.         tText[tActualSize] = '\0';    //————    Terminate C string with null character
  390.         SetWhichService( tText );
  391.     }
  392.     else
  393.     {
  394.         SetWhichService( nil );
  395.     }
  396.     return tErr;
  397. }
  398.  
  399. //—————————————————————————————————————————————————————————————————————————————————————
  400. //    AERequest::SetupParameterList    -    Get the AppleEvent's 'extp' parameter
  401. //                                It contains the list of parameters for the Service
  402. //—————————————————————————————————————————————————————————————————————————————————————
  403. OSErr
  404. AERequest::SetupParameterList()
  405. {
  406.     OSErr            tErr;
  407.     AEDescList        tParamDesc;
  408.     VUList*            tParamValue;
  409.     
  410.     tErr = AEGetParamDesc(    fMessagePtr,
  411.                             kVUAESrvcParameters,
  412.                             typeAEList,
  413.                             &tParamDesc );
  414.     if( tErr != noErr )
  415.     {
  416.             //————    Some services may have no parameters, 
  417.             //————    so allow errAEDescNotFound error
  418.         if( tErr == errAEDescNotFound )
  419.         {
  420.             return noErr;
  421.         }
  422.         else
  423.         {
  424.             return tErr;
  425.         }
  426.     }
  427.     else
  428.     {
  429.         tErr = MakeVUListFromDescList( &tParamDesc, &tParamValue );
  430.         if( tParamValue != nil )
  431.         {
  432.             SetParameterList( tParamValue );
  433.         }
  434.         AEDisposeDesc( &tParamDesc );
  435.     }
  436.     return tErr;
  437. }
  438.  
  439. //—————————————————————————————————————————————————————————————————————————————————————
  440. //    AERequest::SetupRequestIdentifier    -    Get the AppleEvent's return ID
  441. //—————————————————————————————————————————————————————————————————————————————————————
  442. OSErr
  443. AERequest::SetupRequestIdentifier()
  444. {
  445.     OSErr            tErr;
  446.     long            tReturnID;
  447.     DescType        tActualType;
  448.     Size            tActualSize;
  449.     
  450.     tErr = AEGetAttributePtr(    fMessagePtr,
  451.                                 keyReturnIDAttr,
  452.                                 typeLongInteger,
  453.                                 &tActualType,
  454.                                 (Ptr)&tReturnID,
  455.                                 sizeof( long ),
  456.                                 &tActualSize );
  457.     if( tErr == noErr )
  458.     {
  459.             //————    Set the Request Identifier
  460.         SetRequestIdentifier( tReturnID );
  461.     }
  462.     else
  463.     {
  464.             //————    Set the Request Identifier to zero
  465.         SetRequestIdentifier( 0 );
  466.     }
  467.     return tErr;
  468. }
  469.  
  470. //—————————————————————————————————————————————————————————————————————————————————————
  471. //    AERequest::MakeVUListFromDescList    -    Convert the AEDescList 
  472. //                                                    to a VUList object.
  473. //—————————————————————————————————————————————————————————————————————————————————————
  474. OSErr
  475. AERequest::MakeVUListFromDescList( AEDescList* pDescList, VUList** pValue )
  476. {
  477.     OSErr            tErr;
  478.     long            tParamCount;
  479.     long            i;
  480.     AEKeyword        tActualKey;
  481.     DescType        tActualType;
  482.     Size            tActualSize;
  483.     short            tShort;
  484.     long            tLong;
  485.     Boolean            tBoolean;
  486.     char*            tText;
  487.     AEDescList        tDescList;
  488.     VUList*            tReturnVUList;
  489.     VUList*            tVUList;
  490.     
  491.     
  492.         //————    Construct the VUList object to eventually return
  493.     tReturnVUList = new VUList();
  494.     if( tReturnVUList == nil )
  495.     {
  496.         pValue = nil;
  497.         return memFullErr;
  498.     }
  499.  
  500.         //————    Get the number of Descriptors in the list
  501.     tErr = AECountItems( pDescList, &tParamCount );
  502.     if( tErr != noErr )
  503.     {
  504.         pValue = nil;
  505.         return tErr;
  506.     }
  507.  
  508.         //————    For each Descriptor in the list
  509.     for( i = 1; i <= tParamCount; i++ )
  510.     {
  511.             //————    Determine the type of the ith Descriptor
  512.         tErr = AESizeOfNthItem( pDescList, i, &tActualType, &tActualSize );
  513.         if( tErr != noErr )
  514.         {
  515.             break;
  516.         }
  517.         
  518.             //————    Depending on the type,
  519.             //————    Extract the data and put it into ScriptValue
  520.         switch( tActualType )
  521.         {
  522.                 //————————————————————————————————————————————————————
  523.                 //————    typeBoolean, typeFalse, typeTrue
  524.             case typeBoolean:
  525.             case typeTrue:
  526.             case typeFalse:
  527.             {                
  528.                     //————    typeBoolean 
  529.                 if( tActualType == typeBoolean )
  530.                 {
  531.                     tErr = AEGetNthPtr(    pDescList,
  532.                                         i,
  533.                                         tActualType,
  534.                                         &tActualKey,
  535.                                         &tActualType,
  536.                                         (Ptr)&tBoolean,
  537.                                         sizeof(Boolean),
  538.                                         &tActualSize );
  539.                     if( tErr == noErr )
  540.                     {
  541.                         tReturnVUList->PutNthItem( tBoolean );     //————    defaults to appending
  542.                     }
  543.                 }
  544.                 else
  545.                 {
  546.                         //————    typeFalse & typeFalse
  547.                     tReturnVUList->PutNthItem( (Boolean)(tActualType == typeTrue) );     //————    defaults to appending
  548.                 }
  549.             }
  550.             break;
  551.  
  552.                 //————————————————————————————————————————————————————
  553.                 //————    typeShortInteger
  554.             case typeShortInteger:
  555.             {
  556.                 tErr = AEGetNthPtr(    pDescList,
  557.                                     i,
  558.                                     typeShortInteger,
  559.                                     &tActualKey,
  560.                                     &tActualType,
  561.                                     (Ptr)&tShort,
  562.                                     sizeof(short),
  563.                                     &tActualSize );
  564.                 if( tErr == noErr )
  565.                 {
  566.                     tReturnVUList->PutNthItem( tShort ); //————    defaults to appending
  567.                 }
  568.             }
  569.             break;
  570.  
  571.                 //————————————————————————————————————————————————————
  572.                 //————    typeLongInteger
  573.             case typeLongInteger:
  574.             {
  575.                 tErr = AEGetNthPtr(    pDescList,
  576.                                     i,
  577.                                     typeLongInteger,
  578.                                     &tActualKey,
  579.                                     &tActualType,
  580.                                     (Ptr)&tLong,
  581.                                     sizeof(long),
  582.                                     &tActualSize );
  583.                 if( tErr == noErr )
  584.                 {
  585.                     tReturnVUList->PutNthItem( tLong ); //————    defaults to appending
  586.                 }
  587.             }
  588.             break;
  589.  
  590.                 //————————————————————————————————————————————————————
  591.                 //————    typeChar
  592.             case typeChar:
  593.             {
  594.                 tText = new char[ tActualSize + 1 ];
  595.                 if( tText )
  596.                 {
  597.                     tErr = AEGetNthPtr(    pDescList,
  598.                                         i,
  599.                                         typeChar,
  600.                                         &tActualKey,
  601.                                         &tActualType,
  602.                                         (Ptr)tText,
  603.                                         tActualSize + 1,
  604.                                         &tActualSize );
  605.                     if( tErr == noErr )
  606.                     {
  607.                         tText[tActualSize] = '\0';
  608.                         tReturnVUList->PutNthItem( tText ); //————    defaults to appending
  609.                     }
  610.                     delete tText;
  611.                 }
  612.             }
  613.             break;
  614.  
  615.                 //————————————————————————————————————————————————————
  616.                 //————    typeAEList
  617.                 //————    We have to make a recursive call to this same method
  618.                 //————    in order to accomplish translation of an AEDescList
  619.             case typeAEList:
  620.             {
  621.                     //————    Extract the AEDescList
  622.                 tErr = AEGetNthDesc(    pDescList,
  623.                                         i,
  624.                                         typeAEList,
  625.                                         &tActualKey,
  626.                                         &tDescList );
  627.                 if( tErr == noErr )
  628.                 {
  629.                         //————    Now convert the DescList into a VUList
  630.                     tErr = MakeVUListFromDescList( &tDescList, &tVUList );
  631.                     if( tErr == noErr )
  632.                     {
  633.                         if( tVUList != nil )
  634.                         {
  635.                             tReturnVUList->PutNthItem( tVUList ); //————    defaults to appending
  636.                         }
  637.                     }
  638.                     AEDisposeDesc( &tDescList );
  639.                 }
  640.             }
  641.             break;
  642.  
  643.                 //————————————————————————————————————————————————————
  644.                 //————    default case, unknown data type in AEDesc
  645.                 //————    use VUNull to represent an 'undefined'
  646.                 //————    It also forms a place holder so list
  647.                 //————    elements retail their order, and errors are 
  648.                 //————    isolated with less grief
  649.             default:
  650.             {
  651.                 tReturnVUList->PutNthItem( new VUNull() );
  652.             }
  653.             break;
  654.  
  655.         }
  656.         
  657.             //————    Break out of FOR loop if an error was encountered
  658.         if( tErr != noErr )
  659.         {
  660.             break;
  661.         }
  662.     }
  663.     *pValue = tReturnVUList;
  664.     return tErr;
  665. }
  666.  
  667. /*
  668. //—————————————————————————————————————————————————————————————————————————————————————
  669. //    AERequest::AskForMoreTime    - inform V.U. to not let this AppleEvent
  670. //        time out for the indicated number of seconds
  671. //—————————————————————————————————————————————————————————————————————————————————————
  672. void
  673. AERequest::AskForMoreTime( unsigned long pNewTimeOutInterval )
  674. {
  675.     if( !HasBeenCanceled() )
  676.     {
  677.         if( fSendResetTicks - TickCount() < kResetSendThreshold )
  678.         {
  679.                 //————    reset the tool's time-out counter for this request
  680.             ResetTimeOutCounter( pNewTimeOutInterval );
  681.  
  682.                 //————    reset V.U.'s time-out counter for this request
  683.             SendTimeOutResetMessage( pNewTimeOutInterval );
  684.         }
  685.     }
  686. }
  687.  
  688. //—————————————————————————————————————————————————————————————————————————————————————
  689. //    AERequest::ResetTimeOutCounter - inform V.U. to not let this Request time out
  690. //—————————————————————————————————————————————————————————————————————————————————————
  691. void
  692. AERequest::ResetTimeOutCounter( unsigned long pNewTimeOutInterval )
  693. {    
  694.         //————    Set up the Time Manager task to fire again at a later time
  695.     if( !HasBeenCanceled() )
  696.     {
  697.             //————    Keep Track of when we'll time out
  698.         fSendResetTicks = TickCount() + (pNewTimeOutInterval * 60);
  699.     }
  700. }
  701. */
  702.  
  703. //—————————————————————————————————————————————————————————————————————————————————————
  704. //    AERequest::ResetTimeOutCounter    - inform V.U. to not let this AppleEvent
  705. //        time out for the indicated number of seconds
  706. //—————————————————————————————————————————————————————————————————————————————————————
  707. void
  708. AERequest::ResetTimeOutCounter( unsigned long pNewTimeOutInterval )
  709. {
  710.     const    unsigned long     kResetSendThreshold    =    600;
  711.     
  712.     if( !HasBeenCanceled() )
  713.     {
  714.         if( fSendResetTicks - TickCount() < kResetSendThreshold )
  715.         {
  716.                 //————    Send message to V.U. to reset the time out counter
  717.             SendTimeOutResetMessage( pNewTimeOutInterval );
  718.  
  719.                 //————    Call Parent class method
  720.             Request::ResetTimeOutCounter( pNewTimeOutInterval );
  721.         }
  722.     }
  723. }
  724.  
  725.  
  726. //—————————————————————————————————————————————————————————————————————————————————————
  727. //    AERequest::SendTimeOutResetMessage - Send an AppleEvent to V.U. to
  728. //        reset the Time Out counter for this AppleEvent
  729. //—————————————————————————————————————————————————————————————————————————————————————
  730. OSErr
  731. AERequest::SendTimeOutResetMessage( unsigned long pNewTimeOutInterval )
  732. {
  733.     OSErr            tErr;
  734.     AEAddressDesc    tAddressDesc;
  735.     AppleEvent        tDummyReply;
  736.  
  737.         //————    If we have not already built an event for resetting the timer, do so now
  738.     if( !fHaveResetTimerMsg )
  739.     {
  740.             //————    Get the Target Address Descriptor from the existing default reply AppleEvent
  741.         tErr = AEGetAttributeDesc(    fReplyPtr,
  742.                                     keyAddressAttr,
  743.                                     typeWildCard,
  744.                                     &tAddressDesc );
  745.         if( tErr != noErr )
  746.         {
  747.                 //————    not much further we can do, except return the error code
  748.             return tErr;
  749.         }
  750.     
  751.         
  752.             //————    Construct the AppleEvent for sending to V.U.
  753.         tErr = AECreateAppleEvent(    kVUAETool,
  754.                                     kVUAEWaitLonger,
  755.                                     &tAddressDesc,
  756.                                     kAutoGenerateReturnID,
  757.                                     kAnyTransactionID,
  758.                                     &fResetTimerMsg );
  759.             //————    We no longer need the Address descriptor
  760.         AEDisposeDesc( &tAddressDesc );
  761.         if( tErr != noErr )
  762.         {
  763.                 //————    not much further we can do, except return the error code
  764.             return tErr;
  765.         }
  766.         
  767.             //————    Put the same return ID as the original AppleEvent from V.U.
  768.             //————    V.U. uses the return ID to determine which AppleEvent needs its timer reset
  769.         tErr = AEPutAttributePtr(    &fResetTimerMsg,
  770.                                        keyReturnIDAttr,
  771.                                        typeLongInteger,
  772.                                        (Ptr)&fReturnID,
  773.                                       sizeof( long ) );
  774.         
  775.             //————    We now have an AppleEvent that we can send, and we need to dispose of later
  776.         fHaveResetTimerMsg = true;
  777.     }
  778.     
  779.         //————    Put the amount of time required to complete the current service request
  780.         //————    into the AppleEvent
  781.     tErr = AEPutParamPtr(    &fResetTimerMsg,
  782.                                kVUAEWaitAmount,
  783.                                typeMagnitude,
  784.                                (Ptr)&pNewTimeOutInterval,
  785.                               sizeof( pNewTimeOutInterval ) );
  786.     if( tErr != noErr )
  787.     {
  788.             //————    not much further we can do, except return the error code
  789.         return tErr;
  790.     }
  791.     
  792.     
  793.     tErr = AESend(    &fResetTimerMsg,
  794.                     &tDummyReply,
  795.                     kAENoReply + kAENeverInteract,
  796.                     kAEHighPriority,
  797.                     kAEDefaultTimeout,
  798.                     nil,
  799.                     nil );
  800.     if( tErr != noErr )
  801.     {
  802.             //————    not much further we can do, except return the error code
  803.         return tErr;
  804.     }
  805.  
  806.     return noErr;
  807. }
  808.  
  809. //—————————————————————————————————————————————————————————————————————————————————————
  810. //    AERequest::SendResult    - send the result back to VU
  811. //—————————————————————————————————————————————————————————————————————————————————————
  812. void
  813. AERequest::SendResult()
  814. {
  815.     OSErr        tErr = noErr;
  816.     
  817.         //————    If a return value exists, install it in the reply event
  818.     if( fReturnValue != nil )
  819.     {
  820.         tErr = PutReturnValueIntoReplyEvent();
  821.     }    
  822.     
  823.     if( tErr != noErr )
  824.     {
  825.         DebugStr("\pAERequest::SendResult Error in PutReturnValueIntoReplyEvent().");
  826.     }    
  827.  
  828.         //————    Resume the processing of this AppleEvent pair
  829.         //————    This causes the reply event to be sent back to V.U.
  830.         //————    The AE Manager will delete the request and reply Apple events.
  831.     tErr = AEResumeTheCurrentEvent(    fMessagePtr,
  832.                                        fReplyPtr,
  833.                                     NewAEEventHandlerProc(kAENoDispatch),
  834.                                     0 );
  835.     if( tErr == noErr )
  836.     {
  837.         //————    If it was resumed properly we should not dispose of it later
  838.         fSuspended     = false;
  839.     }
  840.  
  841. }
  842.  
  843. //—————————————————————————————————————————————————————————————————————————————————————
  844. //    AERequest::PutReturnValueIntoReplyEvent    -    Convert the ScriptValue 
  845. //                                                        to an AE Descriptor.
  846. //—————————————————————————————————————————————————————————————————————————————————————
  847. OSErr
  848. AERequest::PutReturnValueIntoReplyEvent()
  849. {
  850.     OSErr            tErr;
  851.     Boolean            tBoolean;
  852.     short            tShort;
  853.     long            tLong;
  854.     char*            tText;
  855.     unsigned short    tTextSize;
  856.     AEDescList        tDescList;
  857.     long            tVUAESrvcResults;
  858.         
  859.         //————    APPLESCRIPT COMPATIBILITY CHECK:
  860.         //————    Put the value into the reply event according to its kind
  861.         //————    note: VU 2.1 recognizes non-standard and standard results
  862.     if( this->UseStandardReplyType() )
  863.     {
  864.         tVUAESrvcResults = kVUAESrvcResults;        //————    AppleScript and VU 2.1
  865.     }
  866.     else
  867.     {
  868.         tVUAESrvcResults = kVUAEOldSrvcResults;        //————    VU 2.0, 2.0.1, and 2.1
  869.     }
  870.     
  871.         //————    Put the value into the reply event according to its kind
  872.     switch( fReturnValue->GetValueKind() )
  873.     {
  874.         case kVUBooleanKind:
  875.         {
  876.             tBoolean = ((VUBoolean*)fReturnValue)->GetBoolean();
  877.             if( tBoolean )
  878.             {
  879.                 tErr = AEPutParamPtr(    fReplyPtr,
  880.                                         tVUAESrvcResults,
  881.                                         typeTrue,
  882.                                         (Ptr)&tBoolean,
  883.                                         sizeof(Boolean) );
  884.             }
  885.             else
  886.             {
  887.                 tErr = AEPutParamPtr(    fReplyPtr,
  888.                                         tVUAESrvcResults,
  889.                                         typeFalse,
  890.                                         (Ptr)&tBoolean,
  891.                                         sizeof(Boolean) );
  892.             }
  893.             if( tErr != noErr )
  894.             {
  895.                 SetErrorCode( tErr );
  896.                 SetErrorMessage( "Failed to install return value into the reply." );
  897.             }
  898.         }
  899.         break;
  900.         
  901.         case kVUNumberKind:
  902.         {
  903.             tShort = ((VUNumber*)fReturnValue)->GetNumber();
  904.             tErr = AEPutParamPtr(    fReplyPtr,
  905.                                        tVUAESrvcResults,
  906.                                        typeShortInteger,
  907.                                        (Ptr)&tShort,
  908.                                        sizeof(short) );
  909.             if( tErr != noErr )
  910.             {
  911.                 SetErrorCode( tErr );
  912.                 SetErrorMessage( "Failed to install return value into the reply." );
  913.             }
  914.         }
  915.         break;
  916.         
  917.         case kVULongNumberKind:
  918.         {
  919.             tLong = ((VULongNumber*)fReturnValue)->GetNumber();
  920.             tErr = AEPutParamPtr(    fReplyPtr,
  921.                                        tVUAESrvcResults,
  922.                                        typeLongInteger,
  923.                                        (Ptr)&tLong,
  924.                                        sizeof(long) );
  925.             if( tErr != noErr )
  926.             {
  927.                 SetErrorCode( tErr );
  928.                 SetErrorMessage( "Failed to install return value into the reply." );
  929.             }
  930.         }
  931.         break;
  932.         
  933.         case kVUStringKind:
  934.         {
  935.             tText = ((VUString*)fReturnValue)->GetText();
  936.             if( tText != nil )
  937.             {
  938.                 if( (tTextSize = strlen( tText )) > 0)
  939.                 {
  940.                     tErr = AEPutParamPtr(    fReplyPtr,
  941.                                             tVUAESrvcResults,
  942.                                             typeChar,
  943.                                             (Ptr)tText,
  944.                                             tTextSize );
  945.                     if( tErr != noErr )
  946.                     {
  947.                         SetErrorCode( tErr );
  948.                         SetErrorMessage( "Failed to install return value into the reply." );
  949.                     }
  950.                 }
  951.             }
  952.         }
  953.         break;
  954.         
  955.         case kVUListKind:
  956.         {
  957.             tErr = MakeDescListFromVUList( (VUList*)fReturnValue, &tDescList );
  958.             if( tErr == noErr )
  959.             {
  960.                 tErr = AEPutParamDesc(    fReplyPtr,
  961.                                         tVUAESrvcResults,
  962.                                         &tDescList );
  963.                 AEDisposeDesc( &tDescList );
  964.             }
  965.         }
  966.         break;
  967.  
  968.         default:
  969.         {
  970.         
  971.         }
  972.         break;
  973.     }
  974.  
  975.  
  976.     return tErr;
  977. }
  978.  
  979. //—————————————————————————————————————————————————————————————————————————————————————
  980. //    AERequest::MakeDescListFromVUList    -    Convert the VUList 
  981. //                                                    to a pDescList object.
  982. //—————————————————————————————————————————————————————————————————————————————————————
  983. OSErr
  984. AERequest::MakeDescListFromVUList( VUList* pValue, AEDescList* pDescList )
  985. {
  986.     OSErr            tErr;
  987.     short            tItemCount;
  988.     short            i;
  989.     ScriptValue*    tVal;
  990.     Boolean            tBoolean;
  991.     short            tShort;
  992.     long            tLong;
  993.     char*            tText;
  994.     AEDescList        tDescList;
  995.     ValueKind        tValueKind;
  996.     
  997.         //————    Create the AEDescList to fill with the values in the VUList
  998.     tErr = AECreateList( nil, 0, false, pDescList );
  999.     if( tErr != noErr )
  1000.     {
  1001.         return tErr;
  1002.     }
  1003.         //————    Get the number of items in the VUList
  1004.     tItemCount = pValue->GetCount();
  1005.     
  1006.         //————    Put each item of the VUList, into the AEDescList
  1007.     for( i = 1; i <= tItemCount; i++ )
  1008.     {
  1009.             //————    Get the ith ScriptValue object from the VUList
  1010.         tValueKind = kVUAnyKind;
  1011.         tErr = pValue->GetNthItem( i, tVal, tValueKind );
  1012.         if( tVal )
  1013.         {
  1014.                 //————    if we got one, process it according to its kind
  1015.             switch( tValueKind )
  1016.             {
  1017.  
  1018.                     //————    VUBoolean object
  1019.                 case kVUBooleanKind:
  1020.                 {
  1021.                     tBoolean = ((VUBoolean*)tVal)->GetBoolean();
  1022.                     tErr = AEPutPtr(    pDescList,
  1023.                                           i,
  1024.                                           typeBoolean,
  1025.                                           (Ptr)&tBoolean,
  1026.                                           sizeof(Boolean) );
  1027.                 }
  1028.                 break;
  1029.  
  1030.                     //————    VUNumber object
  1031.                 case kVUNumberKind:
  1032.                 {
  1033.                     tShort = ((VUNumber*)tVal)->GetNumber();
  1034.                     tErr = AEPutPtr(    pDescList,
  1035.                                           i,
  1036.                                           typeShortInteger,
  1037.                                           (Ptr)&tShort,
  1038.                                           sizeof(short) );
  1039.                 }
  1040.                 break;
  1041.  
  1042.                     //————    VULongNumber object
  1043.                 case kVULongNumberKind:
  1044.                 {
  1045.                     tLong = ((VULongNumber*)tVal)->GetNumber();
  1046.                     tErr = AEPutPtr(    pDescList,
  1047.                                           i,
  1048.                                           typeLongInteger,
  1049.                                           (Ptr)&tLong,
  1050.                                           sizeof(long) );
  1051.                 }
  1052.                 break;
  1053.  
  1054.                     //————    VUString object
  1055.                 case kVUStringKind:
  1056.                 {
  1057.                     tText = ((VUString*)tVal)->GetText();
  1058.                     if( tText )
  1059.                     {
  1060.                         tErr = AEPutPtr(    pDescList,
  1061.                                             i,
  1062.                                             typeChar,
  1063.                                             (Ptr)tText,
  1064.                                             strlen(tText) );
  1065.                     }
  1066.                 }
  1067.                 break;
  1068.  
  1069.                     //————    VUList object
  1070.                 case kVUListKind:
  1071.                 {
  1072.                     tErr = MakeDescListFromVUList( (VUList*)tVal, &tDescList );
  1073.                     if( tErr == noErr )
  1074.                     {
  1075.                         tErr = AEPutDesc(    pDescList,
  1076.                                             i,
  1077.                                             &tDescList );
  1078.                         AEDisposeDesc( &tDescList );
  1079.                     }
  1080.                 }
  1081.                 break;
  1082.  
  1083.                 default:
  1084.                 {
  1085.                 }
  1086.                 break;
  1087.             }
  1088.                 //————    Break out of for loop, if there was an error
  1089.             if( tErr != noErr )
  1090.             {
  1091.                 break;
  1092.             }
  1093.         }
  1094.     }
  1095.  
  1096.         //————    if there was an error, dispose of the AEDescList created earlier
  1097.     if( tErr != noErr )
  1098.     {
  1099.         AEDisposeDesc( &tDescList );
  1100.     }
  1101.     return tErr;
  1102. }
  1103.  
  1104.  
  1105. //—————————————————————————————————————————————————————————————————————————————————————
  1106. //    AERequest::FixAEManagerBugPart1    - copy the Apple Event and its result to fix a bug.
  1107. //————        Duplicate the AppleEvent Record, and reset the pointers
  1108. //————        SBR 12/01/94: This is to fix a bug in the AE Manager, which is
  1109. //————        kind enough to trash the AppleEvent sometime after you suspend it.
  1110. //————        All code uses fMessagePtr and fReplyPtr, so this is transparent. 
  1111. //—————————————————————————————————————————————————————————————————————————————————————
  1112. void
  1113. AERequest::FixAEManagerBugPart1()
  1114. {
  1115.     OSErr        tErr = noErr;
  1116.     
  1117.     gTheApplication->fMessagePtrOrig = nil;
  1118.     gTheApplication->fReplyPtrOrig = nil;
  1119.  
  1120.         //————    use true to fix this bug the old way, false for the new way 
  1121.     if( true )
  1122.     {
  1123.             //————    The method used in the old template may not always work, 
  1124.             //————    because it does not duplicate embedded AEDesc's that 
  1125.             //————    have separate memory allocation. When these are disposed
  1126.             //————    by AEResumeTheCurrentEvent(), what happens to the 
  1127.             //————    embedded AEDesc's in the original (trashed) AppleEvent?
  1128.  
  1129.             //————    Note: in practice, this method has worked just fine!
  1130.         fMessage     = *fMessagePtr;
  1131.         fMessagePtr    = &fMessage;
  1132.     
  1133.         fReply        = *fReplyPtr;
  1134.         fReplyPtr     = &fReply;
  1135.  
  1136.         return;
  1137.     }
  1138.     else
  1139.     {
  1140.             //————    Save the original pointers for debugging this problem.
  1141.             //————    Once the copies are made, we can delete the originals, 
  1142.             //————    but we can not delete them now, while in their handler.
  1143.             //————    They are deleted in Request::FixAEManagerBugPart2(),
  1144.         gTheApplication->fMessagePtrOrig = fMessagePtr;
  1145.         gTheApplication->fReplyPtrOrig = fReplyPtr;
  1146.     
  1147.             //————    Duplicate the message AppleEvent Record
  1148.         tErr =  AEDuplicateDesc( fMessagePtr, &fMessage );
  1149.         
  1150.         if( tErr != noErr )
  1151.         {
  1152.             DebugStr( "\pAERequest::FixAEManagerBugPart1 Error AEDuplicateDesc fMessagePtr, &fMessage." );
  1153.         }    
  1154.         fMessagePtr    = &fMessage;
  1155.     
  1156.             //————    Duplicate the reply AppleEvent Record
  1157.         tErr =  AEDuplicateDesc( fReplyPtr, &fReply );
  1158.         
  1159.         if( tErr != noErr )
  1160.         {
  1161.             DebugStr( "\pAERequest::FixAEManagerBugPart1 Error AEDuplicateDesc fReplyPtr, &fReply.");
  1162.         }    
  1163.         fReplyPtr = &fReply;
  1164.     }
  1165. }
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179. /*
  1180.     if( tDo201Reply )        //————    Send a VU 2.0.1 version of this AppleEvent reply
  1181.     {
  1182.         Size        tSize;
  1183.         DescType    tType;
  1184.         AEDesc        tDesc;
  1185.         OSType        tVUEventClass = kVUAETool;    
  1186.         AppleEvent    tReplyFrom201Send;    
  1187.         
  1188.             //————    Duplicate the reply AppleEvent Record
  1189.         tErr =  AEDuplicateDesc( fReplyPtr, &fReply201 );
  1190.         fReply201Ptr = &fReply201;
  1191.         
  1192.         if( tErr != noErr )
  1193.         {
  1194.             DebugStr("\pAEPutAttributePtr Error AEDuplicateDesc fReplyPtr, &fReply201.");
  1195.         }    
  1196.             //————    Change the 201 reply's class id to 'v.u.'
  1197.             //————    Do this before any errors can occur
  1198.         tErr =  AEPutAttributePtr(    fReply201Ptr,
  1199.                                     keyEventClassAttr,
  1200.                                     typeType,
  1201.                                     (Ptr) &tVUEventClass,
  1202.                                     sizeof( OSType ) );
  1203.         if( tErr != noErr )
  1204.         {
  1205.             DebugStr("\pAEPutAttributePtr Error Change the 201 reply class.");
  1206.         }    
  1207.     
  1208.  
  1209.         if( fReturnValue != nil )
  1210.         {
  1211.                 //————    Move the reply data from the direct parameter
  1212.                 //————    to the the kVUAESrvcResults201 parameter
  1213.             tErr =  AEGetParamDesc(    fReplyPtr,
  1214.                                     kVUAESrvcResults,
  1215.                                     typeWildCard, 
  1216.                                     &tDesc );
  1217.             if( tErr != noErr )
  1218.             {
  1219.                 DebugStr("\pAEGetParamDesc Error Move the reply data.");
  1220.             }    
  1221.         
  1222.     
  1223.             if( tErr == noErr )
  1224.                 tErr =  AEPutParamDesc(    fReply201Ptr,
  1225.                                         kVUAESrvcResults201,
  1226.                                         &tDesc );
  1227.             if( tErr != noErr )
  1228.             {
  1229.                 DebugStr("\pAEPutParamDesc Error AEPutParamDesc fReply201Ptr kVUAESrvcResults201.");
  1230.             }    
  1231.         
  1232.     
  1233.             
  1234.                 //————    Delete the data from the direct parameter
  1235.             if( tErr == noErr )
  1236.                 tErr =  AEDeleteParam(    fReply201Ptr,
  1237.                                         kVUAESrvcResults );
  1238.             if( tErr != noErr )
  1239.             {
  1240.                 DebugStr("\pAEDeleteParam Error AEDeleteParam fReply201Ptr.");
  1241.             }    
  1242.             
  1243.         }
  1244.  
  1245.             //————    Send the VU 2.0.1 reply AppleEvent
  1246.         if( tErr == noErr )
  1247.             tErr =  AESend(    fReply201Ptr,
  1248.                             &tReplyFrom201Send,
  1249.                             kAENoReply,
  1250.                             kAENormalPriority,
  1251.                             kNoTimeOut,
  1252.                             nil, nil  );
  1253.         if( tErr != noErr )
  1254.         {
  1255.             DebugStr("\pAESend Error AESend    fReply201Ptr.");
  1256.         }    
  1257.  
  1258.         
  1259.         if( tErr == noErr )
  1260.             tErr =  AEDisposeDesc(     &tDesc );
  1261.         if( tErr != noErr )
  1262.         {
  1263.             DebugStr("\pAEDisposeDesc Error creating VU 2.0.1 reply AppleEvent.");
  1264.         }    
  1265.         
  1266.  
  1267.         if( fReply201Ptr != nil )
  1268.         {
  1269.             AEDisposeDesc( fReply201Ptr );
  1270.             fReply201Ptr = nil;
  1271.         }
  1272.         
  1273.         if( tErr != noErr )
  1274.         {
  1275.             DebugStr("\pError creating VU 2.0.1 reply AppleEvent.");
  1276.         }    
  1277.  
  1278.     }
  1279. */
  1280.     
  1281.